查看原文
其他

云原生 etcd 系列|为什么值得学习?

奇伢 奇伢云存储 2023-04-23
坚持思考,就会很酷


什么是 etcd ?


etcd 是 CoreOS 团队于 2013 年 6 月发起的开源项目。etcd 官网上有这么一段话:

A distributed, reliable key-value store for the most critical data of a distributed system

etcd 是一个分布式、高可靠的 kv 系统,基于 Go 语言实现,内部使用 raft 协议来保证数据一致性和高可靠性。

哦,就是一个 kv 系统哦,etcd 一般用来做什么呢?

对于 etcd 的定位其实在名字里亦可窥见,etcd 这个名字拆开来看就是 etc distributed ,也是就是分布式的 etc 嘛),大家都知道 linux 的 etc 目录就是单机的配置中心。所以 etcd 的应用定位其实就是分布式的配置中心系统嘛,目的就是为服务集群提供一个的全局性配置中心


etcd 为什么值得学?


 1   超火项目背书


etcd 有两个重要项目为其背书:CoreOS,Kubernetes,有人甚至号称 etcd 是云原生的基石之一。

为什么会这么说?

因为 etcd 在其中扮演的角色太重要了,Kubernetes 把核心元数据信息存储在里面。

etcd 在非常多的互联网大厂里都有深度的应用,如果应聘一些云原生的岗位,对 etcd 的熟悉会是很好的亮点。


 2   优秀代码借鉴


etcd 的数据一致性和高可靠是基于 raft 协议实现的。如果有童鞋对 raft 精通理论,但是苦于没有代码实践,这是一个非常好的学习 demo 。

etcd 对 raft 的封装那简直了,分层抽象的太厉害了。raft 模块几乎就只集中了状态机的实现,把 wal 啥的都抽出去了,在 raft 状态机中,对于日志的使用抽象出了 Storage 接口。

所以单就代码来说,真的值得学习一波。


etcd 的特点


  • 简单:接口简单,使用简单;
  • 安全:支持 TLS 证书认证;
  • 强一致性:通过 raft 协议保证数据的强一致性,实现 leader 到 follower 节点的正确复制;
  • 高可用性:集群能自动处理单点故障,网络分区等情况,对外提供高可靠、一致性的数据访问;
  • 性能不错:看官网的 benchmark 数据是 10000 次每秒的写入;

其实经过了 k8s 等超大型的项目验证,etcd 已经是一个非常成熟的项目了。


怎么入手学习?


下面聊聊怎么去学习,这篇是开篇文章。


 1   代码仓库


奇伢很早就拉了个仓库出来,用于阅读 etcd 的代码,版本是 v3.4.10 。

https://github.com/liqingqiya/readcode-etcd-v3.4.10

一直在不断的在这个仓库里加注释,该仓库代码可直接编译,建议 Go 版本 >= 1.14 。

etcd 说白了就是是 kv 存储,只不过这个 kv 存储是分布式的,数据是多副本冗余的,kv 是有多版本功能的。

既然是多节点那最重要的是一致性,etcd 使用了 raft 算法解决了数据多节点的一致性。

说起来 etcd 也是个不小的项目,要撸开源项目最好的就是找到一个切入点,从一个很小的点开始,慢慢往外延伸。etcd 考虑到这点,提供了一个非常好的演示项目 raftexample 。


 2   raftexample


这个模块旨在通过一个极简的例子帮助大家理解 raft 模块在 etcd 中的使用姿势。理解 raft 的模块对理解 etcd 整体流程有非常大的帮助。

所以,第一步就是去撸一遍 raft 相关的代码,etcd 的业务从抽象模块来讲运行在 raft 模块,只要把 raft 相关模块理解了,etcd 就算理解 50 % ,剩下的基本都是业务功能。

raftexample 的目录位于 etcd/contrib/raftexample/ ,这个目录是一个完整的 package,实现了一个极简的 kv 存储,就是为了专门理解 raft 的。

➜  raftexample git:(master) ✗ tree -L 1
.
├── httpapi.go      # 最上层的模块,对外提供 http api,我们命名为 api 层;
├── kvstore.go      # kv 存储的实现,业务层的实现,我们命名为 service 层;
├── raft.go         # 承上启下的模块,对上对接 service 模块,对下对接 raft 状态机模块;
├── listener.go     # 和 raftNode 是一起的;
├── main.go         # 入口文件

0 directories, 10 files

具体的模块划分为四层:



下一步,开始编译。


 3   编译 raftexample


克隆仓库下来:

git clone https://github.com/liqingqiya/readcode-etcd-v3.4.10.git

编译(可以把一些依赖包下载下来):

root@ubuntu:~/code/github/readcode-etcd-v3.4.10/src/go.etcd.io/etcd# make
....

go.etcd.io/etcd/etcdctl
./bin/etcd --version
etcd Version: 3.4.10
Git SHA: b516720
Go Version: go1.14.4
Go OS/Arch: linux/amd64
./bin/etcdctl version
etcdctl version: 3.4.10
API version: 3.4

这样需要的一些依赖包自动就下载下来了。然后,我们就去编译 raftexample 这个程序。

root@ubuntu:~/code/github/readcode-etcd-v3.4.10/src/go.etcd.io/etcd/contrib/raftexample# go build -gcflags=all="-N -l"

编译出 raftexample 的二进制就代表成功了,具有了学习的素材。按照 README 的提示,我们用 goreman 来启动程序:

goreman start

goreman 读的是当前目录的 Procfile 文件,这个文件是这样写的:

root@ubuntu:~/code/github/readcode-etcd-v3.4.10/src/go.etcd.io/etcd/contrib/raftexample# cat Procfile 
# Use goreman to run `go get github.com/mattn/goreman`
raftexample1: ./raftexample --id 1 --cluster http://127.0.0.1:12379,http://127.0.0.1:22379,http://127.0.0.1:32379 --port 12380
raftexample2: ./raftexample --id 2 --cluster http://127.0.0.1:12379,http://127.0.0.1:22379,http://127.0.0.1:32379 --port 22380
raftexample3: ./raftexample --id 3 --cluster http://127.0.0.1:12379,http://127.0.0.1:22379,http://127.0.0.1:32379 --port 32380

也就是启动 3 个 raftexample 进程,分别使用了不同的端口,这样就省去了我们人为的键入,方便一些。

goreman start 执行,你就会发现拉起了 3 个进程,这组成了一个最简单的 raft 集群。

接下来,我们就调试+阅读这个程序的代码,来理解 raft 是怎么回事。

奇伢梳理了一系列 etcd 的深度剖析文章,以后整理出来分享,先抛出一张 raftexample 模块图,用于描述 raftexample 业务层 -> raftNode -> raft 状态机 这三层的交互关系,它们之间多通过 channel 进行交互



后记


后续不定期深度分享 etcd 原理,敬请期待。点赞、在看 是对奇伢最大的支持。

~完~


往期推荐



往期推荐



聊聊奇伢如何学习 Linux 内核源码

存储基础 | 神奇!我的文件有个“洞”

深度细节 | Go 的 panic 的秘密都在这

Go 存储基础 | 怎么使用 direct io ?



坚持思考,方向比努力更重要。关注我:奇伢云存储。

欢迎加我好友,技术交流。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存